{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CIFAR-10 Outlier Detection\n",
    "![demo](./demo.png)\n",
    "\n",
    "In this example, we will deploy an image classification model along with an outlier detector trained on the same dataset. For in depth details on creating an outlier detection model for your own dataset, check out the [Alibi Detect](https://github.com/SeldonIO/alibi-detect) project and its associated [documentation](https://docs.seldon.io/projects/alibi-detect/en/latest/). They also provide [documentation for this CIFAR10 sample](https://docs.seldon.io/projects/alibi-detect/en/latest/examples/od_vae_cifar10.html).\n",
    "\n",
    "\n",
    "Prequisites:\n",
    "\n",
    " * Running cluster with \n",
    "    * [KServe installed](https://github.com/kserve/kserve/blob/master/README.md#hammer_and_wrench-installation)\n",
    "    * [Knative Eventing installed](https://knative.dev/docs/install/yaml-install/eventing/install-eventing-with-yaml/#install-knative-eventing) >= 1.2\n",
    " \n",
    "_Tested on GKE and kind with Knative 1.7 and Istio 1.15.0_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!pip install -r requirements_notebook.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup Resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "namespace/cifar10 created\n"
     ]
    }
   ],
   "source": [
    "!kubectl create namespace cifar10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting broker.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile broker.yaml\n",
    "apiVersion: eventing.knative.dev/v1\n",
    "kind: Broker\n",
    "metadata:\n",
    " name: default\n",
    " namespace: cifar10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "broker.eventing.knative.dev/default created\n"
     ]
    }
   ],
   "source": [
    "!kubectl create -f broker.yaml"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting event-display.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile event-display.yaml\n",
    "apiVersion: apps/v1\n",
    "kind: Deployment\n",
    "metadata:\n",
    "  name: hello-display\n",
    "  namespace: cifar10\n",
    "spec:\n",
    "  replicas: 1\n",
    "  selector:\n",
    "    matchLabels: &labels\n",
    "      app: hello-display\n",
    "  template:\n",
    "    metadata:\n",
    "      labels: *labels\n",
    "    spec:\n",
    "      containers:\n",
    "        - name: event-display\n",
    "          image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display\n",
    "\n",
    "---\n",
    "\n",
    "kind: Service\n",
    "apiVersion: v1\n",
    "metadata:\n",
    "  name: hello-display\n",
    "  namespace: cifar10\n",
    "spec:\n",
    "  selector:\n",
    "    app: hello-display\n",
    "  ports:\n",
    "  - protocol: TCP\n",
    "    port: 80\n",
    "    targetPort: 8080"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "deployment.apps/hello-display created\n",
      "service/hello-display created\n"
     ]
    }
   ],
   "source": [
    "!kubectl apply -f event-display.yaml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create the KServe image classification model for CIFAR10. We include a `logger` for requests."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting cifar10.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile cifar10.yaml\n",
    "apiVersion: \"serving.kserve.io/v1beta1\"\n",
    "kind: \"InferenceService\"\n",
    "metadata:\n",
    "  name: \"tfserving-cifar10\"\n",
    "  namespace: cifar10\n",
    "spec:\n",
    "    predictor:\n",
    "      tensorflow:\n",
    "        storageUri: \"gs://seldon-models/tfserving/cifar10/resnet32\"\n",
    "      logger:\n",
    "        mode: all\n",
    "        url: http://broker-ingress.knative-eventing.svc.cluster.local/cifar10/default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inferenceservice.serving.kserve.io/tfserving-cifar10 created\n"
     ]
    }
   ],
   "source": [
    "!kubectl apply -f cifar10.yaml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create the pretrained VAE Cifar10 Outlier Detector. We forward replies to the event-display we started."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting cifar10od.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile cifar10od.yaml\n",
    "apiVersion: serving.knative.dev/v1\n",
    "kind: Service\n",
    "metadata:\n",
    "  name: vae-outlier\n",
    "  namespace: cifar10\n",
    "spec:\n",
    "  template:\n",
    "    metadata:\n",
    "      annotations:\n",
    "        autoscaling.knative.dev/minScale: \"1\"\n",
    "    spec:\n",
    "      containers:\n",
    "      - image: seldonio/alibi-detect-server:1.12.0\n",
    "        imagePullPolicy: IfNotPresent\n",
    "        args:\n",
    "        - --model_name\n",
    "        - cifar10od\n",
    "        - --http_port\n",
    "        - '8080'\n",
    "        - --protocol\n",
    "        - tensorflow.http\n",
    "        - --storage_uri\n",
    "        - gs://seldon-models/alibi-detect/od/OutlierVAE/cifar10\n",
    "        - --reply_url\n",
    "        - http://hello-display.cifar10\n",
    "        - --event_type\n",
    "        - org.kubeflow.serving.inference.outlier\n",
    "        - --event_source\n",
    "        - org.kubeflow.serving.cifar10od\n",
    "        - OutlierDetector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "service.serving.knative.dev/vae-outlier created\n"
     ]
    }
   ],
   "source": [
    "!kubectl apply -f cifar10od.yaml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a Knative trigger to forward logging events to our Outlier Detector."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting trigger.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile trigger.yaml\n",
    "apiVersion: eventing.knative.dev/v1\n",
    "kind: Trigger\n",
    "metadata:\n",
    "  name: vaeoutlier-trigger\n",
    "  namespace: cifar10\n",
    "spec:\n",
    "  broker: default\n",
    "  filter:\n",
    "    attributes:\n",
    "      type: org.kubeflow.serving.inference.request\n",
    "  subscriber:\n",
    "    ref:\n",
    "      apiVersion: serving.knative.dev/v1\n",
    "      kind: Service\n",
    "      name: vae-outlier\n",
    "      namespace: cifar10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "trigger.eventing.knative.dev/vaeoutlier-trigger created\n"
     ]
    }
   ],
   "source": [
    "!kubectl apply -f trigger.yaml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get the IP address of the Istio Ingress Gateway. _This assumes you have installed Istio with a LoadBalancer._"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n",
    "CLUSTER_IP = CLUSTER_IPS[0]\n",
    "print(CLUSTER_IP)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "CLUSTER_IP = \"localhost:8080\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you are using Kind or Minikube, you will need to port-forward to the Istio Ingress Gateway and run the following:\n",
    "\n",
    "```\n",
    "$ INGRESS_GATEWAY_SERVICE=$(kubectl get svc --namespace istio-system --selector=\"app=istio-ingressgateway\" --output jsonpath='{.items[0].metadata.name}')\n",
    "$ kubectl port-forward --namespace istio-system svc/${INGRESS_GATEWAY_SERVICE} 8080:80\n",
    "$ CLUSTER_IP=\"localhost:8080\"\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tfserving-cifar10.cifar10.example.com\n"
     ]
    }
   ],
   "source": [
    "SERVICE_HOSTNAMES = !(kubectl get inferenceservice -n cifar10 tfserving-cifar10 -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n",
    "SERVICE_HOSTNAME_CIFAR10 = SERVICE_HOSTNAMES[0]\n",
    "print(SERVICE_HOSTNAME_CIFAR10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vae-outlier.cifar10.example.com\n"
     ]
    }
   ],
   "source": [
    "SERVICE_HOSTNAMES = !(kubectl get ksvc -n cifar10 vae-outlier -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n",
    "SERVICE_HOSTNAME_VAEOD = SERVICE_HOSTNAMES[0]\n",
    "print(SERVICE_HOSTNAME_VAEOD)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)\n"
     ]
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import json\n",
    "import tensorflow as tf\n",
    "\n",
    "tf.keras.backend.clear_session()\n",
    "\n",
    "from alibi_detect.od.vae import OutlierVAE\n",
    "from alibi_detect.utils.perturbation import apply_mask\n",
    "from alibi_detect.utils.visualize import plot_feature_outlier_image\n",
    "import requests\n",
    "\n",
    "train, test = tf.keras.datasets.cifar10.load_data()\n",
    "X_train, y_train = train\n",
    "X_test, y_test = test\n",
    "\n",
    "X_train = X_train.astype(\"float32\") / 255\n",
    "X_test = X_test.astype(\"float32\") / 255\n",
    "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)\n",
    "classes = (\n",
    "    \"plane\",\n",
    "    \"car\",\n",
    "    \"bird\",\n",
    "    \"cat\",\n",
    "    \"deer\",\n",
    "    \"dog\",\n",
    "    \"frog\",\n",
    "    \"horse\",\n",
    "    \"ship\",\n",
    "    \"truck\",\n",
    ")\n",
    "\n",
    "\n",
    "def show(X):\n",
    "    plt.imshow(X.reshape(32, 32, 3))\n",
    "    plt.axis(\"off\")\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "def predict(X):\n",
    "    formData = {\"instances\": X.tolist()}\n",
    "    headers = {}\n",
    "    headers[\"Host\"] = SERVICE_HOSTNAME_CIFAR10\n",
    "    res = requests.post(\n",
    "        \"http://\" + CLUSTER_IP + \"/v1/models/tfserving-cifar10:predict\",\n",
    "        json=formData,\n",
    "        headers=headers,\n",
    "    )\n",
    "    if res.status_code == 200:\n",
    "        return classes[np.array(res.json()[\"predictions\"])[0].argmax()]\n",
    "    else:\n",
    "        print(\"Failed with \", res.status_code)\n",
    "        return []\n",
    "\n",
    "\n",
    "def outlier(X):\n",
    "    formData = {\"instances\": X.tolist()}\n",
    "    headers = {\n",
    "        \"Alibi-Detect-Return-Feature-Score\": \"true\",\n",
    "        \"Alibi-Detect-Return-Instance-Score\": \"true\",\n",
    "        \"ce-namespace\": \"default\",\n",
    "        \"ce-modelid\": \"cifar10\",\n",
    "        \"ce-type\": \"io.seldon.serving.inference.request\",\n",
    "        \"ce-id\": \"1234\",\n",
    "        \"ce-source\": \"localhost\",\n",
    "        \"ce-specversion\": \"1.0\",\n",
    "    }\n",
    "    headers[\"Host\"] = SERVICE_HOSTNAME_VAEOD\n",
    "    res = requests.post(\"http://\" + CLUSTER_IP + \"/\", json=formData, headers=headers)\n",
    "    if res.status_code == 200:\n",
    "        od = res.json()\n",
    "        od[\"data\"][\"feature_score\"] = np.array(od[\"data\"][\"feature_score\"])\n",
    "        od[\"data\"][\"instance_score\"] = np.array(od[\"data\"][\"instance_score\"])\n",
    "        return od\n",
    "    else:\n",
    "        print(\"Failed with \", res.status_code)\n",
    "        return []"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Normal Prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "'truck'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "idx = 1\n",
    "X = X_train[idx : idx + 1]\n",
    "show(X)\n",
    "predict(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now call our outlier detector directly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "od_preds = outlier(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After a few seconds, we can check the event display for an outlier detection prediction. This should be false."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Outlier False\n"
     ]
    }
   ],
   "source": [
    "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n",
    "data = []\n",
    "for i in range(0, len(res)):\n",
    "    if res[i] == \"Data,\":\n",
    "        data.append(res[i + 1])\n",
    "j = json.loads(json.loads(data[-1]))\n",
    "print(\"Outlier\", j[\"data\"][\"is_outlier\"] == [1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Outlier Prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "np.random.seed(0)\n",
    "X_mask, mask = apply_mask(\n",
    "    X.reshape(1, 32, 32, 3),\n",
    "    mask_size=(10, 10),\n",
    "    n_masks=1,\n",
    "    channels=[0, 1, 2],\n",
    "    mask_type=\"normal\",\n",
    "    noise_distr=(0, 1),\n",
    "    clip_rng=(0, 1),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "'truck'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "show(X_mask)\n",
    "predict(X_mask)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now call our outlier detector directly and use the feature scores returned to gather more information about why it predicted an outlier below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "od_preds = outlier(X_mask)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we'll confirm that an outlier was found by checking the event display for a new message."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Outlier True\n"
     ]
    }
   ],
   "source": [
    "res = !kubectl logs -n cifar10 $(kubectl get pod -n cifar10 -l app=hello-display -o jsonpath='{.items[0].metadata.name}')\n",
    "data = []\n",
    "for i in range(0, len(res)):\n",
    "    if res[i] == \"Data,\":\n",
    "        data.append(res[i + 1])\n",
    "j = json.loads(json.loads(data[-1]))\n",
    "print(\"Outlier\", j[\"data\"][\"is_outlier\"] == [1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we'll plot the feature scores returned by the outlier detector along with the original image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABiIAAAF7CAYAAABfBJMKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAABbYklEQVR4nO3deZxdVZnv/2fvc06dmqcMZCQTCWNADDJPAgo2iCDCBZFZ0RZE+yd0e29L07SKE63YtjaIdBywRSZpLoqKQCPQKC1KmAJJIAlJSCWpeTrj3uv+wS8hRQJ8V6hlkfB5v178QdU3zx7O3utZ+6w6VZFzzhkAAAAAAAAAAEAA8VjvAAAAAAAAAAAA2HGxEAEAAAAAAAAAAIJhIQIAAAAAAAAAAATDQgQAAAAAAAAAAAiGhQgAAAAAAAAAABAMCxEAAAAAAAAAACAYFiIAAAAAAAAAAEAwLEQAAAAAAAAAAIBgWIgAAAAAAAAAAADBsBCBt6x//Md/tCiKtunf/uAHP7AoimzFihWju1ObWbFihUVRZD/4wQ+CbQMA/hK2NmYeeeSRduSRR47ZPr1dnHvuudbY2DjWuzFqzj33XJs5c+ZY7waAMURPGTv0FAA7EvrJ2KGfIBQWIhDE008/bR/5yEds6tSpls/nbcqUKXbmmWfa008/Pda7BgBveaHG0KuuusruuOOO0dnJUZSmqf3oRz+yAw44wNrb262pqcnmzZtnZ599tv3+978f693bJsVi0b75zW/aAQccYC0tLVZbW2vz5s2ziy++2JYsWTLWu/eWsHjxYjvuuOOssbHR2tvb7ayzzrINGzaM9W4BOxx6Cj1lR/foo4/aJz/5SVuwYIHlcrlt/mE2AK+PfkI/2ZGlaWo/+MEP7MQTT7Tp06dbQ0OD7bXXXvbFL37RisXiWO/eDiM71juAHc/tt99uZ5xxhrW3t9sFF1xgs2bNshUrVtgNN9xgt956q91000128sknv2Gdz3/+8/a5z31um/bhrLPOstNPP93y+fw2/XsAGCujNYZuzVVXXWUf+tCH7KSTTnrD7G9+85tt2sa2uOSSS+w73/mOfeADH7AzzzzTstmsPffcc3b33Xfb7Nmz7cADD/yL7cto6OzstOOOO84ee+wxO+GEE+zDH/6wNTY22nPPPWc33XSTfe9737NyuTzWuzmmVq9ebYcffri1tLTYVVddZYODg3b11Vfbk08+aY8++qjV1NSM9S4COwR6Cj3l7eCXv/ylff/737e9997bZs+e/bZ/Mw0IgX5CP9nRDQ8P23nnnWcHHnigfeITn7CJEyfaI488YldccYXde++9dt9997HQPRocMIqWLVvm6uvr3W677ebWr18/4nsbNmxwu+22m2toaHDPP//8a9YYHBwMvZujYvny5c7M3MKFC8d6VwDsIEZjDH09DQ0N7pxzztni6wsXLnRm5pYvX75Ndd9IkiSuUChs9XsdHR0uiiL3sY99bIvvpWnq1q1bF2SftqZSqbhSqfSm6xx//PEujmN36623bvG9YrHoPvvZz276/3POOcc1NDS86W2+VZxzzjluxowZb5j767/+a1dXV+dWrly56Wv33HOPMzN33XXXBdxD4O2DnjISPWX7o/aUjo4ONzw87Jxz7qKLLnK8zQGMLvrJSPST7Y/ST0qlknv44Ye3+PqVV17pzMzdc889gfbu7YVfzYRR9fWvf92Gh4fte9/7nk2YMGHE98aPH2/XXXedDQ0N2de+9jUze+XvQDzzzDP24Q9/2Nra2uzQQw8d8b3NFQoFu+SSS2z8+PHW1NRkJ554oq1Zs8aiKLJ//Md/3JTb2u8SnDlzpp1wwgn20EMP2f7772+1tbU2e/Zs+9GPfjRiG93d3XbppZfa/PnzrbGx0Zqbm+1973ufLVq0aBTPFABsyXcMNXvt33f56jE0iiIbGhqyH/7whxZFkUVRZOeee+5r7svWfv9qqVSyK664wnbZZRfL5/M2ffp0+9u//VsrlUojclEU2cUXX2w/+clPbM8997R8Pm+/+tWvtrqd5cuXm3PODjnkkC2+F0WRTZw4ccTXent77W/+5m9s5syZls/nbdq0aXb22WdbZ2fnpsz69evtggsusJ122slqa2ttn332sR/+8Icj6mz8Oz9XX321XXPNNTZnzhzL5/P2zDPPmJnZs88+ax/60Iesvb3damtrbb/99rM777zzNc/XRn/4wx/sF7/4hV1wwQV2yimnbPH9fD5vV1999RZfX7NmjZ100knW2NhoEyZMsEsvvdSSJBmRufrqq+3ggw+2cePGWV1dnS1YsMBuvfXWrZ63iy++2O644w7ba6+9LJ/P25577rnFa7DxGlm2bJmde+651traai0tLXbeeefZ8PDwFnVvvPFGW7BggdXV1Vl7e7udfvrptmrVqjc8J1tz22232QknnGA777zzpq8dc8wxNm/ePLv55pu3qSaAkegpI9FTdtyestNOO1ldXd02/VsAb4x+MhL9ZMfsJzU1NXbwwQdv8fWNn/RZvHixd01siV/NhFH1f//v/7WZM2faYYcdttXvH3744TZz5kz7xS9+MeLrp556qs2dO9euuuoqc869Zv1zzz3Xbr75ZjvrrLPswAMPtAceeMCOP/54ef+WLVtmH/rQh+yCCy6wc845x/793//dzj33XFuwYIHtueeeZmb2wgsv2B133GGnnnqqzZo1y9atW2fXXXedHXHEEfbMM8/YlClT5O0BgI9tHUMVP/7xj+2jH/2o7b///nbhhReamdmcOXPkf5+mqZ144on20EMP2YUXXmi77767Pfnkk/bNb37TlixZssXvdb3vvvvs5ptvtosvvtjGjx//mn8cbMaMGWZmdsstt9ipp55q9fX1r7kPg4ODdthhh9nixYvt/PPPt3e+853W2dlpd955p61evdrGjx9vhULBjjzySFu2bJldfPHFNmvWLLvlllvs3HPPtd7eXvv0pz89oubChQutWCzahRdeaPl83trb2+3pp5+2Qw45xKZOnWqf+9znrKGhwW6++WY76aST7Lbbbnvdj51vfBA466yzhLP6siRJ7Nhjj7UDDjjArr76avvtb39r//zP/2xz5syxv/7rv96U+9a3vmUnnniinXnmmVYul+2mm26yU0891e66664teuFDDz1kt99+u33yk5+0pqYm+5d/+Rc75ZRT7MUXX7Rx48aNyJ522mk2a9Ys+/KXv2x/+tOf7Pvf/75NnDjRvvrVr27KfOlLX7LLL7/cTjvtNPvoRz9qGzZssG9/+9t2+OGH25///GdrbW2Vj3fNmjW2fv1622+//bb43v7772+//OUv5VoAXhs9hZ7ydugpAMKjn9BP3s79pKOjw8xeXnTDKBjbD2RgR9Lb2+vMzH3gAx943dyJJ57ozMz19/e7K664wpmZO+OMM7bIbfzeRo899pgzM/eZz3xmRO7cc891ZuauuOKKTV/b2kf4ZsyY4czM/e53v9v0tfXr17t8Pj/iI2jFYtElSTJiG8uXL3f5fN790z/904ivGb+aCcAo2ZYx1LnX/pjpq8dQ5/w+9nzEEUe4I444YtP///jHP3ZxHLsHH3xwxL+99tprnZmN+Birmbk4jt3TTz/9usey0dlnn+3MzLW1tbmTTz7ZXX311W7x4sVb5P7hH/7BmZm7/fbbt/hemqbOOeeuueYaZ2buxhtv3PS9crnsDjroINfY2LjpvG0cw5ubm7f4iPnRRx/t5s+f74rF4oj6Bx98sJs7d+7rHsvJJ5/szMz19PRIx37OOec4MxvRX5xzbt9993ULFiwY8bWNv3Zi8+Paa6+93FFHHTXi62bmampq3LJlyzZ9bdGiRc7M3Le//e1NX9t4jZx//vlbHMO4ceM2/f+KFStcJpNxX/rSl0bknnzySZfNZkd8XfnY8//8z/84M3M/+tGPtvjeZZdd5sxsxLkH4I+eQk/Z3I7cU16NX80EjC76Cf1kc2+nfrLRMccc45qbm+Vzh9fHr2bCqBkYGDAzs6amptfNbfx+f3//pq994hOfeMP6Gz+u9clPfnLE1z/1qU/J+7jHHnuMWMWfMGGC7brrrvbCCy9s+lo+n7c4fvnWSJLEurq6rLGx0XbddVf705/+JG8LAHy8mTH0L+GWW26x3Xff3XbbbTfr7Ozc9N9RRx1lZmb333//iPwRRxxhe+yxh1R74cKF9q//+q82a9Ys+/nPf26XXnqp7b777nb00UfbmjVrNuVuu+0222effbb60z4bP+L9y1/+0iZNmmRnnHHGpu/lcjm75JJLbHBw0B544IER/+6UU04Z8RHz7u5uu+++++y0006zgYGBTcfZ1dVlxx57rC1dunTEPr3axtfljV7HV3t1HzzssMNG9CYzG/FrJ3p6eqyvr88OO+ywrfamY445ZsRPk+29997W3Ny8Rc3X2nZXV9emY7n99tstTVM77bTTRrz2kyZNsrlz527x2r+RQqFgZi/321erra0dkQGwbegp9JTN7cg9BUBY9BP6yebebv3kqquust/+9rf2la98hU/rjRJ+NRNGzcYBbWOjei1ba2SzZs16w/orV660OI63yO6yyy7yPm7+u6g3amtrs56enk3/n6apfetb37Lvfve7tnz58hG//+7VHxUDgNHyZsbQv4SlS5fa4sWLt/i9sButX79+xP8r4/pGcRzbRRddZBdddJF1dXXZww8/bNdee63dfffddvrpp9uDDz5oZmbPP//8Vn+n6eZWrlxpc+fO3bSgvNHuu+++6fuvt5/Lli0z55xdfvnldvnll291G+vXr7epU6du9XvNzc1m9vLrpE5Wa2trtzivr+5NZmZ33XWXffGLX7THH398xO+8ffXfUzLT+t1rZdva2szs5QeJ5uZmW7p0qTnnbO7cuVvd/1wu9xpHtnUbH1Ze/Xt7zcyKxeKIDIBtQ0+hp2xuR+4pAMKin9BPNvd26ic/+9nP7POf/7xdcMEFI34VFd4cFiIwalpaWmzy5Mn2xBNPvG7uiSeesKlTp24aCM3+cm84ZDKZrX7dbfZ3Ka666iq7/PLL7fzzz7cvfOEL1t7ebnEc22c+8xlL0/Qvsp8A3n62dQzd2gTPzLb4I2JvVpqmNn/+fPvGN76x1e9Pnz59xP9v67g+btw4O/HEE+3EE0+0I4880h544AFbuXLlpt/TOtpevZ8bx/lLL73Ujj322K3+m9dbAN9tt93MzOzJJ598zd+j+2qv1Zs29+CDD9qJJ55ohx9+uH33u9+1yZMnWy6Xs4ULF9p//Md/yDU373dqNk1Ti6LI7r777q1mGxsb33D/Nzd58mQzM1u7du0W31u7dq21t7dv9dMSAHT0lJfRU7ZuR+opAMKin7yMfrJ1O2o/ueeee+zss8+2448/3q699tptroMtsRCBUXXCCSfY9ddfbw899JAdeuihW3z/wQcftBUrVtjHP/5x79ozZsywNE1t+fLlI1Y8ly1b9qb2+dVuvfVWe/e732033HDDiK/39vbyx2kABLUtY2hbW5v19vZukX31T9WYvfYDgWLOnDm2aNEiO/roo99UHR/77befPfDAA7Z27VqbMWOGzZkzx5566qnX/TczZsywJ554wtI0HfETR88+++ym77+e2bNnm9nLP0FzzDHHeO/z+9//fvvyl79sN954ozzJV9x2221WW1trv/71r0e8Sb9w4cJR28ZrmTNnjjnnbNasWTZv3rw3XW/q1Kk2YcIE++Mf/7jF9x599FF7xzve8aa3AYCe8mr0lFfsSD0FQHj0k5HoJ6/YEfvJH/7wBzv55JNtv/32s5tvvtmyWd46H038jQiMqssuu8zq6urs4x//uHV1dY34Xnd3t33iE5+w+vp6u+yyy7xrb1z1/e53vzvi69/+9re3fYe3IpPJbLEae8stt7zu79sDgNGwLWPonDlzrK+vb8RPKa1du9Z+/vOfb1G/oaFhqw8EitNOO83WrFlj119//RbfKxQKNjQ0tE11Ozo67Jlnntni6+Vy2e69916L43jTT/eccsoptmjRoq0e28Zx+6/+6q+so6PDfvazn236XrVatW9/+9vW2NhoRxxxxOvuz8SJE+3II4+06667bqs/sb9hw4bX/fcHHXSQHXfccfb973/f7rjjjq0e16WXXvq6NbYmk8lYFEUjfopsxYoVW93GaPvgBz9omUzGrrzyyi36o3Nui2tVccopp9hdd91lq1at2vS1e++915YsWWKnnnrqm95nAPSUzdFTRtrRegqAsOgnr6CfjLSj9ZPFixfb8ccfbzNnzrS77rqLXxcbAMs6GFVz5861H/7wh3bmmWfa/Pnz7YILLrBZs2bZihUr7IYbbrDOzk776U9/OuKP06gWLFhgp5xyil1zzTXW1dVlBx54oD3wwAO2ZMkSM3tzq+ibO+GEE+yf/umf7LzzzrODDz7YnnzySfvJT36yaQUaAELZljH09NNPt7/7u7+zk08+2S655BIbHh62f/u3f7N58+Zt8QfCFixYYL/97W/tG9/4hk2ZMsVmzZplBxxwgLRvZ511lt188832iU98wu6//3475JBDLEkSe/bZZ+3mm2+2X//617bffvt5H/Pq1att//33t6OOOsqOPvpomzRpkq1fv95++tOf2qJFi+wzn/nMpk+jXXbZZXbrrbfaqaeeaueff74tWLDAuru77c4777Rrr73W9tlnH7vwwgvtuuuus3PPPdcee+wxmzlzpt1666328MMP2zXXXCP93trvfOc7duihh9r8+fPtYx/7mM2ePdvWrVtnjzzyiK1evdoWLVr0uv/+Rz/6kb33ve+1D37wg/b+97/fjj76aGtoaLClS5faTTfdZGvXrrWrr77a6zwdf/zx9o1vfMOOO+44+/CHP2zr16+373znO7bLLru84Ufl36w5c+bYF7/4Rfvf//t/24oVK+ykk06ypqYmW758uf385z+3Cy+80PvB5f/8n/9jt9xyi7373e+2T3/60zY4OGhf//rXbf78+XbeeecFOhLg7YWeQk95LTtaT1m5cqX9+Mc/NjPb9Gm7L37xi2b28k8Zn3XWWaN7EMDbDP2EfvJadqR+MjAwYMcee6z19PTYZZddZr/4xS+22N5BBx002ofx9uOAAJ544gl3xhlnuMmTJ7tcLucmTZrkzjjjDPfkk0+OyF1xxRXOzNyGDRu2qLHxe5sbGhpyF110kWtvb3eN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\n",
      "text/plain": [
       "<Figure size 2000x2000 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_feature_outlier_image(od_preds, X_mask, X_recon=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tear Down"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!kubectl delete ns cifar10"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "outlier-detection",
   "language": "python",
   "name": "outlier-detection"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.7"
  },
  "vscode": {
   "interpreter": {
    "hash": "8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
